#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include <Metro.h> //Include Metro library

// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ   3  // MUST be an interrupt pin!
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10
// Use hardware SPI for the remaining pins
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
                                         SPI_CLOCK_DIVIDER); // you can change this clock speed

#define WLAN_SSID       "Matrix"           // cannot be longer than 32 characters!
#define WLAN_PASS       "ursacheundwirkung123"
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY   WLAN_SEC_WPA2

// Carriots parameters
#define WEBSITE  "api.carriots.com"
#define API_KEY "fbdd9def209ba543f00552d2c1cbb08682c11ac6618a95bb6b9d1b6fbf8999f2"
#define DEVICE  "defaultDevice@m3rlin.m3rlin"

uint32_t ip;

Metro needHaertBeat = Metro(1000); 

void LogValues(int Temp, int Moisture)
{
  /* Initialise the module */
  if (!cc3000.begin())
  {
    Serial.println(F("Couldn't begin()! Check your wiring?"));
    return;
  }
  
  //Connect
  if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
    Serial.println(F("Failed!"));
    return;
  }
  
  /* Wait for DHCP to complete */
  Serial.println(F("\nRequest DHCP"));
  unsigned long startT = millis();
  while ((!cc3000.checkDHCP()) && (!isTimeout(startT,10000)))
  {delay(200);}  
 
  // Prepare JSON for Carriots & get length
  int length = 0;
  char tempBuff[5];
  itoa(Temp,tempBuff,10);
  String data = "{\"protocol\":\"v2\",\"device\":\""+String(DEVICE)+"\",\"at\":\"now\",\"data\":{\"Temperature\":"+String(tempBuff)+",\"Moisture\":"+String(Moisture)+"}}";
  length = data.length();
  
  // Print Info for debug purposes
  Serial.println("carriots.apikey: " + String(API_KEY));
  Serial.println("Content-Length: " + String(length));
  Serial.println();
  Serial.println(data);
  Serial.flush();
  
  // Send request
  Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 80);
  if (client.connected()) {
    Serial.println("Connected!");
    client.println("POST /streams HTTP/1.1");
    client.println("Host: api.carriots.com");
    client.println("Accept: application/json");
    client.println("User-Agent: Arduino-Carriots");
    client.println("Content-Type: application/json");
    client.println("carriots.apikey: " + String(API_KEY));
    client.println("Content-Length: " + String(length));
    client.println("Connection: close");
    client.println();
    client.println(data);
    
  } else {
    Serial.println(F("Connection failed"));    
    return;
  }
  
  Serial.println(F("-------------------------------------"));
  startT = millis();
  while (client.connected() && (!isTimeout(startT,10000))) {
    while (client.available() && (!isTimeout(startT,10000))) {
      char c = client.read();
      Serial.print(c); 
    }
  }
  client.close();
  Serial.println(F("\n-------------------------------------"));
  
  Serial.println(F("\nDisconnecting"));
  cc3000.disconnect(); 
}

boolean isTimeout(unsigned long startTime, int timeOut)
{
  if((millis()-startTime)>timeOut){
    Serial.println(F("TimeOut!"));
    return true;
  }
  else
  {
    return false;
  }
}

// Example state machine reading serial input
// Author: Nick Gammon
// Date: 17 December 2011

// the possible states of the state-machine
typedef enum {  NONE, GOT_R, GOT_S, GOT_G } states;

// current state-machine state
states state = NONE;
// current partial number
unsigned int currentValue;

void processRPM (const unsigned int value)
{
  // do something with RPM 
  Serial.print ("RPM = ");
  Serial.println (value);
} // end of processRPM

void processSpeed (const unsigned int value)
{
  // do something with speed 
  Serial.print ("Speed = ");
  Serial.println (value);
} // end of processSpeed

void processGear (const unsigned int value)
{
  // do something with gear 
  Serial.print ("Gear = ");
  Serial.println (value);  
} // end of processGear

void handlePreviousState ()
{
  switch (state)
  {
  case GOT_R:
    processRPM (currentValue);
    break;
  case GOT_S:
    processSpeed (currentValue);
    break;
  case GOT_G:
    processGear (currentValue);
    break;
  }  // end of switch  

  currentValue = 0; 
}  // end of handlePreviousState

void processIncomingByte (const byte c)
{
  if (isdigit (c))
  {
    currentValue *= 10;
    currentValue += c - '0';
  }  // end of digit
  else 
  {

    // The end of the number signals a state change
    handlePreviousState ();

    // set the new state, if we recognize it
    switch (c)
    {
    case 'R':
      state = GOT_R;
      break;
    case 'S':
      state = GOT_S;
      break;
    case 'G':
      state = GOT_G;
      break;
    default:
      state = NONE;
      break;
    }  // end of switch on incoming byte
  } // end of not digit  
  
} // end of processIncomingByte

void setup() {  
  /*   WiFi Module   */
  if (!cc3000.begin())
  {
    Serial.println(F("Couldn't begin()! Check your wiring?"));
    while(1);
  }
  
  //Connect
  if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
    Serial.println(F("Failed!"));
    return;
  }
  
  /* Wait for DHCP to complete */
  Serial.println(F("\nRequest DHCP"));
  unsigned long startT = millis();
  while ((!cc3000.checkDHCP()) && (!isTimeout(startT,10000)))
  {delay(200);}  
 
  // Get the website IP & print it
  ip = 0;
  Serial.print(WEBSITE); Serial.print(F(" -> "));
  while ((ip == 0) && (!isTimeout(startT,10000))) {
    if (! cc3000.getHostByName(WEBSITE, &ip)) {
      Serial.println(F("Couldn't resolve!"));
    }
    delay(500);
  }
  cc3000.printIPdotsRev(ip);
}

void loop() {
  if (needHaertBeat.check() == 1) { 
    Serial.println("HeartBeat");
    Serial.flush();
  }
  String ReadStr;
  while(Serial.available() > 0) {
    char c = Serial.read();
  } 
}

